<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>贪吃蛇游戏</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            display: flex;
            flex-direction: column;
            align-items: center;
            background-color: #f5f5f5;
            margin: 0;
            padding: 20px;
        }

        #game-container {
            display: flex;
            flex-direction: column;
            align-items: center;
            margin-top: 20px;
        }

        #game-canvas {
            border: 2px solid #333;
            background-color: white;
        }

        #score-container {
            display: flex;
            justify-content: space-between;
            width: 400px;
            margin-bottom: 10px;
            font-size: 18px;
        }

        #game-status {
            margin-top: 10px;
            font-size: 20px;
            font-weight: bold;
            height: 24px;
        }

        #restart-btn {
            margin-top: 20px;
            padding: 10px 20px;
            font-size: 16px;
            background-color: #2e8b57;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            display: none;
        }

        #restart-btn:hover {
            background-color: #3cb371;
        }

        .instructions {
            margin-top: 20px;
            text-align: center;
            max-width: 400px;
        }
    </style>
</head>
<body>
<h1>贪吃蛇游戏</h1>

<div id="game-container">
    <div id="score-container">
        <div>当前得分: <span id="current-score">0</span></div>
        <div>最高分: <span id="high-score">0</span></div>
    </div>

    <canvas id="game-canvas" width="400" height="400"></canvas>

    <div id="game-status">准备开始</div>

    <button id="restart-btn">重新开始</button>
</div>

<div class="instructions">
    <p>使用方向键(↑↓←→)或WASD控制蛇的移动方向</p>
    <p>吃到红色食物增长身体，避免撞墙或撞到自己</p>
</div>

<script>
    // 游戏常量
    const GRID_SIZE = 20;
    const CELL_SIZE = 20;
    const GAME_WIDTH = 400;
    const GAME_HEIGHT = 400;

    // 颜色定义
    const COLORS = {
        BACKGROUND: '#ffffff',
        GRID_LINES: '#eeeeee',
        SNAKE_HEAD: '#2e8b57',
        SNAKE_BODY: '#90ee90',
        FOOD: '#ff0000',
        TEXT: '#000000'
    };

    // 方向常量
    const DIRECTIONS = {
        UP: { x: 0, y: -1 },
        DOWN: { x: 0, y: 1 },
        LEFT: { x: -1, y: 0 },
        RIGHT: { x: 1, y: 0 }
    };

    // 键盘按键映射
    const KEY_MAPPINGS = {
        // 方向键
        'ArrowUp': DIRECTIONS.UP,
        'ArrowDown': DIRECTIONS.DOWN,
        'ArrowLeft': DIRECTIONS.LEFT,
        'ArrowRight': DIRECTIONS.RIGHT,
        // WASD键
        'w': DIRECTIONS.UP,
        's': DIRECTIONS.DOWN,
        'a': DIRECTIONS.LEFT,
        'd': DIRECTIONS.RIGHT
    };

    // 游戏状态
    const GAME_STATES = {
        READY: 'ready',
        PLAYING: 'playing',
        GAME_OVER: 'gameOver'
    };

    // 游戏变量
    let canvas, ctx;
    let snake, food, direction, nextDirection;
    let gameState;
    let score, highScore;
    let lastUpdateTime;
    let gameSpeed = 100; // 毫秒每帧

    // DOM元素
    let currentScoreElement, highScoreElement, gameStatusElement, restartButton;

    // 初始化游戏
    function initGame() {
        // 获取DOM元素
        canvas = document.getElementById('game-canvas');
        ctx = canvas.getContext('2d');
        currentScoreElement = document.getElementById('current-score');
        highScoreElement = document.getElementById('high-score');
        gameStatusElement = document.getElementById('game-status');
        restartButton = document.getElementById('restart-btn');

        // 设置事件监听器
        document.addEventListener('keydown', handleKeyDown);
        restartButton.addEventListener('click', resetGame);

        // 从本地存储加载最高分
        highScore = localStorage.getItem('snakeHighScore') || 0;
        highScoreElement.textContent = highScore;

        // 初始化游戏状态
        resetGame();
    }

    // 重置游戏
    function resetGame() {
        // 初始化蛇
        const startX = Math.floor(GRID_SIZE / 2);
        const startY = Math.floor(GRID_SIZE / 2);
        snake = [
            { x: startX, y: startY },
            { x: startX - 1, y: startY },
            { x: startX - 2, y: startY }
        ];

        // 初始化方向
        direction = DIRECTIONS.RIGHT;
        nextDirection = DIRECTIONS.RIGHT;

        // 生成食物
        generateFood();

        // 重置分数
        score = 0;
        currentScoreElement.textContent = score;

        // 设置游戏状态
        gameState = GAME_STATES.READY;
        gameStatusElement.textContent = '按任意方向键开始游戏';

        // 隐藏重新开始按钮
        restartButton.style.display = 'none';

        // 重置计时器
        lastUpdateTime = 0;

        // 绘制初始状态
        drawGame();
    }

    // 生成食物
    function generateFood() {
        let foodPosition;
        let isPositionValid = false;

        while (!isPositionValid) {
            foodPosition = {
                x: Math.floor(Math.random() * GRID_SIZE),
                y: Math.floor(Math.random() * GRID_SIZE)
            };

            // 检查食物是否与蛇身重叠
            isPositionValid = true;
            for (let segment of snake) {
                if (segment.x === foodPosition.x && segment.y === foodPosition.y) {
                    isPositionValid = false;
                    break;
                }
            }
        }

        food = foodPosition;
    }

    // 处理键盘输入
    function handleKeyDown(e) {
        if (gameState === GAME_STATES.GAME_OVER && e.key === ' ') {
            resetGame();
            return;
        }

        const newDirection = KEY_MAPPINGS[e.key];
        if (!newDirection) return;

        // 如果是准备状态，按任意方向键开始游戏
        if (gameState === GAME_STATES.READY) {
            gameState = GAME_STATES.PLAYING;
            gameStatusElement.textContent = '游戏中';
            lastUpdateTime = Date.now();
            requestAnimationFrame(gameLoop);
        }

        // 防止180度转弯
        if (newDirection.x !== -direction.x || newDirection.y !== -direction.y) {
            nextDirection = newDirection;
        }
    }

    // 更新游戏状态
    function updateGame() {
        // 更新方向
        direction = nextDirection;

        // 移动蛇
        const head = { x: snake[0].x + direction.x, y: snake[0].y + direction.y };

        // 检查碰撞
        if (checkCollision(head)) {
            gameOver();
            return;
        }

        // 将新头部添加到蛇身
        snake.unshift(head);

        // 检查是否吃到食物
        if (head.x === food.x && head.y === food.y) {
            // 增加分数
            score++;
            currentScoreElement.textContent = score;

            // 更新最高分
            if (score > highScore) {
                highScore = score;
                highScoreElement.textContent = highScore;
                localStorage.setItem('snakeHighScore', highScore);
            }

            // 生成新食物
            generateFood();
        } else {
            // 如果没有吃到食物，移除尾部
            snake.pop();
        }
    }

    // 检查碰撞
    function checkCollision(head) {
        // 检查墙壁碰撞
        if (head.x < 0 || head.x >= GRID_SIZE || head.y < 0 || head.y >= GRID_SIZE) {
            return true;
        }

        // 检查自撞
        for (let i = 0; i < snake.length; i++) {
            if (head.x === snake[i].x && head.y === snake[i].y) {
                return true;
            }
        }

        return false;
    }

    // 游戏结束
    function gameOver() {
        gameState = GAME_STATES.GAME_OVER;
        gameStatusElement.textContent = '游戏结束! 最终得分: ' + score;
        restartButton.style.display = 'block';
    }

    // 绘制游戏
    function drawGame() {
        // 清除画布
        ctx.fillStyle = COLORS.BACKGROUND;
        ctx.fillRect(0, 0, GAME_WIDTH, GAME_HEIGHT);

        // 绘制网格线
        ctx.strokeStyle = COLORS.GRID_LINES;
        ctx.lineWidth = 0.5;

        for (let i = 0; i <= GRID_SIZE; i++) {
            // 垂直线
            ctx.beginPath();
            ctx.moveTo(i * CELL_SIZE, 0);
            ctx.lineTo(i * CELL_SIZE, GAME_HEIGHT);
            ctx.stroke();

            // 水平线
            ctx.beginPath();
            ctx.moveTo(0, i * CELL_SIZE);
            ctx.lineTo(GAME_WIDTH, i * CELL_SIZE);
            ctx.stroke();
        }

        // 绘制食物
        ctx.fillStyle = COLORS.FOOD;
        ctx.beginPath();
        ctx.arc(
            food.x * CELL_SIZE + CELL_SIZE / 2,
            food.y * CELL_SIZE + CELL_SIZE / 2,
            CELL_SIZE / 2 - 1,
            0,
            Math.PI * 2
        );
        ctx.fill();

        // 绘制蛇
        for (let i = 0; i < snake.length; i++) {
            const segment = snake[i];

            if (i === 0) {
                // 蛇头
                ctx.fillStyle = COLORS.SNAKE_HEAD;
            } else {
                // 蛇身
                ctx.fillStyle = COLORS.SNAKE_BODY;
            }

            ctx.fillRect(
                segment.x * CELL_SIZE + 1,
                segment.y * CELL_SIZE + 1,
                CELL_SIZE - 2,
                CELL_SIZE - 2
            );

            // 为蛇头添加眼睛
            if (i === 0) {
                ctx.fillStyle = 'white';
                const eyeSize = CELL_SIZE / 5;

                // 根据方向确定眼睛位置
                if (direction === DIRECTIONS.RIGHT || direction === DIRECTIONS.LEFT) {
                    // 水平移动时，眼睛在上下
                    ctx.fillRect(
                        segment.x * CELL_SIZE + CELL_SIZE / 2 - eyeSize / 2,
                        segment.y * CELL_SIZE + CELL_SIZE / 4 - eyeSize / 2,
                        eyeSize,
                        eyeSize
                    );
                    ctx.fillRect(
                        segment.x * CELL_SIZE + CELL_SIZE / 2 - eyeSize / 2,
                        segment.y * CELL_SIZE + 3 * CELL_SIZE / 4 - eyeSize / 2,
                        eyeSize,
                        eyeSize
                    );
                } else {
                    // 垂直移动时，眼睛在左右
                    ctx.fillRect(
                        segment.x * CELL_SIZE + CELL_SIZE / 4 - eyeSize / 2,
                        segment.y * CELL_SIZE + CELL_SIZE / 2 - eyeSize / 2,
                        eyeSize,
                        eyeSize
                    );
                    ctx.fillRect(
                        segment.x * CELL_SIZE + 3 * CELL_SIZE / 4 - eyeSize / 2,
                        segment.y * CELL_SIZE + CELL_SIZE / 2 - eyeSize / 2,
                        eyeSize,
                        eyeSize
                    );
                }
            }
        }
    }

    // 游戏循环
    function gameLoop(timestamp) {
        if (gameState !== GAME_STATES.PLAYING) return;

        const currentTime = Date.now();
        const elapsed = currentTime - lastUpdateTime;

        if (elapsed > gameSpeed) {
            updateGame();
            drawGame();
            lastUpdateTime = currentTime - (elapsed % gameSpeed);
        }

        requestAnimationFrame(gameLoop);
    }

    // 启动游戏
    window.onload = initGame;
</script>
</body>
</html>